package thinkingJava.chapter19;
import static util.Print.*;

import java.util.Iterator;
class Mail {
	enum GeneralDelivery {YES,NO1,NO2,NO3,NO4,NO5}
	enum Scannability {UNSCANNABLE,YES1,YES2,YES3,YES4}
	enum Readability {ILLEGIBLE, YES1, YES2, YES3, YES4}
	enum Address {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
	enum ReturnAddress { MISSING, OK1, OK2, OK3, OK4, OK5}
	GeneralDelivery delivery;
	Scannability scannability;
	Readability readability;
	Address address;
	ReturnAddress returnaddress;
	static long counter = 0;
	long id = counter++;
	public String toString() {
		return "Mail " + id;
	}
	public String details() {
		return toString()
			+ ", General Delivery : " + delivery
			+ ", Scannability : " + scannability
			+ ", Readability : " + readability
			+ ", Address : " + address
			+ ", Return Address : " + returnaddress;
	}
	public static Mail randomMail() {
		Mail mail = new Mail();

		mail.delivery = Enums.random(GeneralDelivery.class);
		mail.scannability = Enums.random(Scannability.class);
		mail.address = Enums.random(Address.class);
		mail.returnaddress = Enums.random(ReturnAddress.class);
		mail.readability = Enums.random(Readability.class);

		return mail;
	}
	public static Iterable<Mail> generator(final int count) {
		return new Iterable<Mail>() {
			int n = count;
			public Iterator<Mail> iterator() {
				return new Iterator<Mail>(){
					public boolean hasNext() {
						return n-- > 0;
					}
					public Mail next() {
						return randomMail();
					}
					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}
		};
	}
}
public class PostOffice {
	enum MailHandler {
		GENERAL_DELIVERY {
			boolean handle(Mail m) {
				switch(m.delivery) {
				case YES:
					print("using general delivery for " + m);
					return true;
				default:
						return false;
				}
			}
		},
		MACHINE_SCAN {
			boolean handle(Mail m) {
				switch(m.scannability) {
				case UNSCANNABLE:
					return false;
				default:
					switch(m.address) {
					case INCORRECT:
						return false;
					default :
						print("Delivering " + m + " automatically");
						return true;
					}
				}
			}
		},
		VISUAL_INSPECTION {
			boolean handle(Mail m) {
				switch(m.readability) {
				case ILLEGIBLE:
					return false;
				default:
					switch(m.address) {
					case INCORRECT:
						return false;
					default:
						print("Delivering " + m + " normally");
						return true;
					}
				}
			}
		},
		RETURN_TO_SENDER {
			boolean handle(Mail m) {
				switch(m.returnaddress) {
				case MISSING:
					return false;
				default :
					print("returning " + m + " to sender");
					return true;
				}
			}
		};
		abstract boolean handle(Mail m);
	}
	static void handle(Mail m) {
		for (MailHandler hd : MailHandler.values()) {
			if (hd.handle(m)) {
				return;
			}
		}
		print(m + " is a dead letter");
	}
	public static void main(String[] args) {
		for (Mail mail : Mail.generator(10)) {
			print(mail.details());
			handle(mail);
			print("****************");
		}
	}
}
